package com.baixiaowen.xiaoaointerview.大厂笔试_白板面试篇.Buffer的原理和使用场景;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Random;
import java.util.concurrent.Future;

/**
 * @author Baixiaowen
 */
public class BufferExample {

    public static void main(String[] args) throws Exception {
//        gen();
        read_test_withBuffer();
        read_test_nio();
    }

    public static void gen() throws IOException {
        Random r = new Random();
        String fileName = "word.txt";

        int bufferSize = 4 * 1024;
        BufferedOutputStream fout = new BufferedOutputStream(new FileOutputStream(fileName), bufferSize);

        long start = System.currentTimeMillis();

        for (int i = 0; i < 1000_000_0; i++) {
            for (int j = 0; j < 5; j++) {
                fout.write(97 + r.nextInt(5));
            }
        }

        fout.close();
        System.err.println(System.currentTimeMillis() - start);
    }

    public static void read_test() throws IOException{
        String fileName = "word.txt";
        InputStream in = new FileInputStream(fileName);

        long start = System.currentTimeMillis();

        int b;
        StringBuilder sb = new StringBuilder();
        while ((b = in.read()) != -1) {

        }

        System.err.println(System.currentTimeMillis() - start);
        in.close();
    }

    public static void read_test_withBuffer() throws IOException {
        String fileName = "word.txt";
        InputStream in = new BufferedInputStream(new FileInputStream(fileName));

        long start = System.currentTimeMillis();

        int b;
//        StringBuilder sb = new StringBuilder();
        byte[] bytes = new byte[1024 * 8];
        while ((b = in.read(bytes)) != -1) {

        }

        System.err.println(System.currentTimeMillis() - start);
        in.close();
    }

    /**
     * New I/O
     * @throws IOException
     */
    public static void read_test_nio() throws IOException{

        String fileName = "word.txt";

        // 是一种NIO的编程模型，必须使用Buffer来操作它
        FileChannel channel = new FileInputStream(fileName).getChannel();
        // 1024 * 8 : 一般的操作系统的页表大小，
        // 页表: 操作系统管理内存的最小单位
        ByteBuffer buff = ByteBuffer.allocate(1024*8);

        long start = System.currentTimeMillis();

        while (channel.read(buff) != -1) {

            // 这个时候buff在进行写操作，channel.read 就是channel将数据读入到buff中，即buff在写数据

            // 对buff进行翻转操作，从 写 -> 读
            buff.flip();

            // 从 buff 中读取数据
//            System.err.println(new String(buff.array()));

            // 清空buff
            buff.clear();

        }

        System.err.format("%dms\n", System.currentTimeMillis() - start);

    }

    /**
     * 异步IO
     * @throws Exception
     */
    public static void test_async_read() throws Exception {
        String fileName = "word.txt";

        // 创建异步只读Channel
        AsynchronousFileChannel channel = AsynchronousFileChannel.open(Paths.get(fileName), StandardOpenOption.READ);

        ByteBuffer buf = ByteBuffer.allocate(1024 * 8);
        Future<Integer> operation = channel.read(buf, 0);
        Integer numReads = operation.get();
        buf.flip();
        String chars = new String(buf.slice().array());
        buf.clear();
    }

}
